package framework.classification.entities.lattice.erca;








import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import com.googlecode.erca.Attribute;
import com.googlecode.erca.Entity;
import com.googlecode.erca.clf.Concept;

import framework.classification.entities.ClAbstractEntity;
import framework.classification.entities.ClFunctionRequired;

import framework.entity.ACLFunction;
import framework.entity.ACLInterface;

public class LatticeInterfaceRequiredErca extends LatticeAbstractErca {



	public void calculateReduced(ClAbstractEntity table) {
		conceptToExtends = new HashMap<String, ArrayList<String>>();
		realOperations = new HashMap<String, String>();
		abstractOperations = new HashMap<String, String>();
	
		String name = lattice.getName();
		for (int i = 0; i < lattice.getConcepts().size(); i++) {
			Concept concept = lattice.getConcepts().get(i);
			concept.setName("C"
					+ concept.getName().substring(
							concept.getName().indexOf("_") + 1));
			caculateOperationConcept(concept, table);

		}
	}

	public String getMaxSuperRealInterface(String c) {
		Concept concept = lattice.getConcept(c);
		Iterator<Concept> it = concept.getAllParents().iterator();
		int size = concept.getAllParents().size() - 1;
		while (size >= 0) {
			if (!concept.getAllParents().get(size).getSimplifiedExtent()
					.isEmpty()) {
				return concept.getAllParents().get(size).getSimplifiedExtent()
				.get(0).getName();
			}
			size--;
		}
		return null;
	}

	public void caculateOperationConcept(Concept concept,
			ClAbstractEntity table) {


		//soit le concept à un extent, dans ce cas il represente une interface deja definis
		if (!concept.getSimplifiedExtent().isEmpty()){
			for (Entity ent : concept.getSimplifiedExtent()){
			
				ACLInterface aclinter = new ACLInterface(ent.getName());
				aclinter.setFunctions(table.getAbstractClassfication().getStructure().getInterfacesFonction().get(ent.getName()));
				
				
				
				realOperations.put(aclinter.toString(),concept.getName());
				
				
				if (!conceptToExtends.containsKey(concept.getName()))
					conceptToExtends.put(concept.getName(),new ArrayList<String>());
				if (!conceptToExtends.get(concept.getName()).contains(aclinter.toString()))
					conceptToExtends.get(concept.getName()).add(aclinter.toString());

				if (lattice.getTop() == concept) superEntity = aclinter.toString();
			}

		}
		//soit les extents simplifies sont vide, dans ce cas on reconstruit la fonction abstraite
		//à partir des concepts parents;
		else{
			ACLInterface aclinter = new ACLInterface(table.getName()+concept.getName());

			ArrayList<String> noparam = new ArrayList<String>();
			for (Concept parentConcept : concept.getAllParents()){
				for (Attribute att : parentConcept.getSimplifiedIntent()){

					String funcAtt = att.getDescription();
					ArrayList<ACLFunction> remove = new ArrayList<ACLFunction>();
					ClFunctionRequired cl = table.getAbstractClassfication().getFunctionRequired().get(funcAtt);
					Boolean add = true;

					if (funcAtt.charAt(0) == '!') {noparam.add(funcAtt.substring(1));}
					else{
						for (ACLFunction funcinter : aclinter.getFunctions()){

							//on regarde si les fonctions de l'interface est parente de la fonction funcAtt
							if(cl.getLattice().isParent(funcinter.toString(),funcAtt)) remove.add(funcinter);
							else if (cl.getLattice().isParent(funcAtt,funcinter.toString())) add = false;
						}
						if (add){
							if (!remove.isEmpty()){
								
								for (ACLFunction r : remove){
									
									aclinter.getFunctions().remove(r);
								}
								
							}
							aclinter.getFunctions().add(new ACLFunction(funcAtt,ACLFunction.MODE2));
						}
					}

				}
			}
			
			for (int i=0;i<noparam.size();i++){
				String nopara = noparam.get(i);
				ClFunctionRequired cl = table.getAbstractClassfication().getFunctionRequired().get(nopara);
				for (int j=0;j<aclinter.getFunctions().size();j++){
					String para = aclinter.getFunctions().get(j).toString();
					
					
					if (nopara.equals(para))
						aclinter.getFunctions().remove(j);
					else if (cl.getLattice().isParent(nopara,para))
						aclinter.getFunctions().remove(j);
					else if (table.getLattice().isParent(para,nopara))
						aclinter.getFunctions().remove(j);

				}
			}
			aclinter.setAbstract(true);
			if (!conceptToExtends.containsKey(concept.getName()))
				conceptToExtends.put(concept.getName(),new ArrayList<String>());
			if (!conceptToExtends.get(concept.getName()).contains(aclinter.toString()))
				conceptToExtends.get(concept.getName()).add(aclinter.toString());

			abstractOperations.put(aclinter.toString(),concept.getName());
			if (lattice.getTop() == concept) superEntity = aclinter.toString();
		}

		

		



	}
}






